<?php
/*******************************************************************************

    FinalsClub.org is a platform for students and faculty to collaborate
    and share their knowledge with the world.

    Copyright (C) 2009  Andrew Magliozzi
 
    This file is a part of FinalsClub.org.

    FinalsClub.org is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
    To contact FinalsClub.org, send an email to info@finalsclub.org, or
    send mail to Finals Club, c/o Veritas Tutors, 1132 Massachusetts Avenue,
    Cambridge, MA 02138.

*******************************************************************************/
require_once("cryptutil.php");

class AnnotateApi {
    
    /**
     * url of the A.nnotate server
     *
     * @access private
     * @var    string
     */
    var $_baseurl;
    
    /**
     * url path of the A.nnotate API
     *
     * @access private
     * @var    string
     */
    var $_baseurl_api;
    
    /**
     * url path of the A.nnotate documents
     *
     * @access private
     * @var    string
     */
    var $_baseurl_docs;
    
    /**
     * admin user email of the A.nnotate server
     *
     * @access private
     * @var    string
     */
    var $_admin;
    
    /**
     * API key needed to form A.nnotate auth parameter
     *
     * @access private
     * @var    string
     */
    var $_apikey;
    
    /**
     * Create a new user account
     * 
     * @param string $email Email address to be used as the A.nnotate user name
     * @param string $signature User's nickname that A.nnotate uses
     * 
     * @return boolean true if successfully created, false if unsuccessful
     */
    public function createAccount($email, $signature) {
	$api_call = $this->_baseurl_api . '/createAccount.php?' . $this->_signRequest("createAccount.php", $this->_admin, $this->_apikey, $email) . '&sig=' . $signature;
	$result = $this->callAnnotateAPI($api_call);
	return $result;
    }
    public function updateAccount($email, $signature) {
	$api_call = $this->_baseurl_api . '/updateAccount.php?' . $this->_signRequest("updateAccount.php", $this->_admin, $this->_apikey, $email) . '&sig=' . $signature;
	$result = $this->callAnnotateAPI($api_call);
	return $result;
    }
    
    /**
     * Return an authenticated URL for uploading a file
     * 
     * @param string $email Email address of the A.nnotate account
     * 
     * @return a URL
     */
    public function getFileUploadURL($email) {
	$url = $this->_baseurl_api . '/uploadDocument.php?' . $this->_signRequest("uploadDocument.php", $this->_admin, $this->_apikey, $email);
	return $url;
    }

    /**
     * Return an authenticated URL for logging in and viewing a file
     * 
     * @param string $email Email address of the A.nnotate account
     * @param string $date the a.nnotate document date, i.e. 2008-02-10
     * @param string $code the a.nnotate document code, i.e. fDzQ45dj
     * 
     * @return string a URL
     */
    public function getLoginDisplayFileURL($email, $date, $code) {
	$url = $this->getLoginURL($email);
	$url .= "&loc=pdfnotate.php" . urlencode("?d=".$date."&c=".$code."&nobanner=1"."&sig=sasda&errorloc=about:blank");

	return $url;
    }

    /**
     * Return an authenticated URL for logging in
     * 
     * @param string $email Email address of the A.nnotate account
     * 
     * @return string a URL
     */
    public function getLoginURL($email, $loc = NULL, $errorloc = NULL) {
	$url = $this->_baseurl_api . '/loginAs.php?' . $this->_signRequest("loginAs.php", $this->_admin, $this->_apikey, $email, 24*3600); // remain logged in for a day
	if ($loc != null) {
	    $url .= "&loc=" . urlencode($loc);
	}
	if ($errorloc != null) {
	    $url .= "&errorloc=" . urlencode($errorloc);
	}

	$url .= "&remember=1";
	return $url;
    }

    /**
     * Deleting a specific user file via the A.nnotate API
     * 
     * @param string $email Email address of the A.nnotate account
     * @param string $date the a.nnotate document date, i.e. 2008-02-10
     * @param string $code the a.nnotate document code, i.e. fDzQ45dj
     * 
     * @return string, the return from the A.nnotate API call or false if unsuccessful in contacting the API
     */
    public function deleteDocument($email, $date, $code) {
	$api_call = $this->_baseurl_api . '/deleteDocument.php?' . $this->_signRequest("deleteDocument.php", $this->_admin, $this->_apikey, $email) . '&d=' . $date . '&c=' . $code;
	$result = $this->callAnnotateAPI($api_call);
	return $result;
    }

    /**
     * List documents for a user
     * 
     * @param string $email Email address of the A.nnotate account
     * @param integer $with_meta =1 to include meta info, =0 to only list basic doc info
     * 
     * @return string, the return from the A.nnotate API call or false if unsuccessful in contacting the API
     */
    public function listDocuments($email, $with_meta = false) {
	$api_call = $this->_baseurl_api . '/listDocuments.php?' . ($with_meta ? "withmeta=1&" : '') . $this->_signRequest("listDocuments.php", $this->_admin, $this->_apikey, $email);
	$result = $this->callAnnotateAPI($api_call);
	return $result;
    }

    /**
     * List notes and meta info for a single document
     * 
     * @param string $date the a.nnotate document date, i.e. 2008-02-10
     * @param string $code the a.nnotate document code, i.e. fDzQ45dj
     * 
     * @return string, the return from the A.nnotate API call or false if unsuccessful in contacting the API
     */
    public function listNotes($email, $date, $code, $with_meta = false) {
	$api_call = $this->_baseurl_api . '/listNotes.php?d=' . $date . '&c=' . $code .($with_meta ? "&withmeta=1" : '') . "&" .$this->_signRequest("listNotes.php", $this->_admin, $this->_apikey, $email);

	$result = $this->callAnnotateAPI($api_call);
	return $result;
    }

    /**
     * Return a the base url to the a.nnotate server
     * 
     * @return string
     */
    public function getBaseURL() {
	return $this->_baseurl;
    }

    /**
     * Return a the base url to the a.nnotate server API
     * 
     * @return string
     */
    public function getAPIBaseURL() {
	return $this->_baseurl_api;
    }

    /**
     * Return a the base url to the a.nnotate server API
     * 
     * @return string
     */
    public function getDocsBaseURL() {
	return $this->_baseurl_docs;
    }

    /**
     * Return the encoding of the argument using the encryption in cryptutil.php (doesn't have to be an email)
     * 
     * @return string
     */
    public function encodeEmail($email) {
	return encodeParam($this->_apikey, $email);
    }

    function callAnnotateAPI($request) {
	$result = file_get_contents($request);

	// if an API call fails, note it in the error log.  An error notification to the sys admin may be needed, though.
	if ($result == false) {
	    error_log("Annotate API not responding from \" $request \"");
	    return false;
	}
	else if (substr($result, 0, 3) == "ERR") {
	    error_log("Annotate API error \" $result \" from \" $request \"");
	    return false;
	}
	else {
	    return $result;
	}
    }

    // from A.nnotate api documentation. Use the timeoffset param to "post date" the request for certain api calls.
    function _signRequest( $phpfn, $apiuser, $apikey, $annotateuser, $timeoffset = 0 ) {
	$requesttime = time() + $timeoffset;
	$stringToSign = "$phpfn\n$apiuser\n$requesttime\n$annotateuser";  
	$hasher = new Crypt_HMAC($apikey, "sha1");
	$signature = $this->_hex2b64($hasher->hash($stringToSign));
	return "api-user=".rawurlencode($apiuser).
	    "&api-requesttime=".$requesttime.
	    "&api-annotateuser=".rawurlencode($annotateuser).
	    "&api-auth=".rawurlencode($signature);
    }
    
    function __construct() {
	$this->_baseurl =  sfConfig::get('app_annotate_baseurl');
	$this->_baseurl_api = $this->_baseurl . '/php';
	$this->_baseurl_docs = $this->_baseurl . '/docs';
	$this->_admin =  sfConfig::get('app_annotate_admin');
	$this->_apikey =  sfConfig::get('app_annotate_apikey');
    }
    
    // from amazon S3 php code
    function _hex2b64($str)
    {
	$raw = "";
	for ($i=0; $i < strlen($str); $i+=2)
	    {
		$raw .= chr(hexdec(substr($str, $i, 2)));
	    }
	return base64_encode($raw);
    }
}
